import { Injectable } from "@nestjs/common"
import { AuthorizationEntity } from "./authorization.entity"
import { ProgramEntity } from "../program/program.entity"
import { InjectRepository } from "@nestjs/typeorm"
import { ILike, IsNull, Not, Repository } from "typeorm"
import { getCurrentDate } from "../../utils/getCurrentDate"
import { PiracyService } from "../piracy/piracy.service"

@Injectable()
export class AuthorizationService {
  constructor(
    @InjectRepository(AuthorizationEntity)
    private readonly authorizationEntity: Repository<AuthorizationEntity>,
    @InjectRepository(ProgramEntity)
    private readonly programEntity: Repository<ProgramEntity>,
    private readonly piracyService: PiracyService
  ) {}

  /**
   * Obtain all authorization information
   * @param res
   * @param session
   */
  public async getAll(res: any, session: any): Promise<void> {
    try {
      // Judging character
      if (session.info.character === "admin") {
        const data = await this.authorizationEntity.find()
        res.json(data)
      } else if (session.info.character === "user") {
        const data = await this.authorizationEntity.find({
          where: { user_id: session.info.uid }
        })
        res.json(data)
      }
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Obtain all authorization information with soft deletion
   * @param res
   */
  public async getAllWithDeleted(res: any): Promise<void> {
    try {
      const data = await this.authorizationEntity.find({
        withDeleted: true,
        where: {
          deleteAt: Not(IsNull())
        }
      })
      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Fuzzy search authorization information
   * @param body
   * @param res
   * @param session
   */
  public async search(body: any, res: any, session: any): Promise<void> {
    try {
      if (session.info.character === "admin") {
        const result = await this.authorizationEntity.find({
          where: [
            {
              body: ILike(`%${body.body}%`)
            },
            {
              app_name: ILike(`%${body.body}%`)
            }
          ]
        })
        res.json(result)
      } else if (session.info.character === "user") {
        const result = await this.authorizationEntity.find({
          where: [
            {
              body: ILike(`%${body.body}%`),
              user_id: session.info.uid
            },
            {
              app_name: ILike(`%${body.body}%`),
              user_id: session.info.uid
            }
          ]
        })
        res.json(result)
      }
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Fuzzy search authorization information with soft deletion
   * @param body
   * @param res
   */
  public async searchWithDeleted(body: any, res: any): Promise<void> {
    try {
      const result = await this.authorizationEntity.find({
        withDeleted: true,
        where: [
          {
            body: ILike(`%${body.body}%`),
            deleteAt: Not(IsNull())
          },
          {
            app_name: ILike(`%${body.body}%`),
            deleteAt: Not(IsNull())
          }
        ]
      })
      res.json(result)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Add authorization information
   * @param body
   * @param res
   */
  public async add(body: any, res: any): Promise<void> {
    try {
      await this.authorizationEntity.save({
        create_date: getCurrentDate(),
        ...body
      })
      res.json({ status: "success", message: "授权信息添加成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Modifying authorization information
   * @param body
   * @param res
   */
  public async update(body: any, res: any): Promise<void> {
    try {
      await this.authorizationEntity.update(body.id, body.data)
      res.json({ status: "success", message: "授权信息修改成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Soft deletion authorization information
   * @param body
   * @param res
   */
  public async delete(body: any, res: any): Promise<void> {
    try {
      const { id } = body
      await this.authorizationEntity.softDelete(id)
      res.json({ status: "success", message: "授权信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Real deletion authorization information
   * @param body
   * @param res
   */
  public async remove(body: any, res: any): Promise<void> {
    try {
      const { id } = body
      await this.authorizationEntity.delete(id)
      res.json({ status: "success", message: "授权信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Batch soft deletion of authorization information
   * @param body
   * @param res
   */
  public async deleteGroup(body: any, res: any): Promise<void> {
    const { ids } = body
    try {
      for (let i = 0; i < ids.length; i++) {
        await this.authorizationEntity.softDelete(ids[i])
      }
      res.json({ status: "success", message: "授权信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Batch real deletion of authorization information
   * @param body
   * @param res
   */
  public async removeGroup(body: any, res: any): Promise<void> {
    const { ids } = body
    try {
      for (let i = 0; i < ids.length; i++) {
        await this.authorizationEntity.delete(ids[i])
      }
      res.json({ status: "success", message: "授权信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Restore authorization information
   * @param body
   * @param res
   */
  public async restore(body: any, res: any): Promise<void> {
    try {
      const { id, app_id, status, body: b } = body
      const isRepeat = await this.authorizationEntity.find({
        where: {
          app_id,
          status,
          body: b
        }
      })
      if (isRepeat.length !== 0) {
        res.json({ status: "error", message: "恢复失败，授权信息重复！" })
        return
      }
      await this.authorizationEntity.update(id, { deleteAt: null })
      res.json({ status: "success", message: "应用信息恢复成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Check if authorization is granted
   * @param body
   * @param res
   */
  public async check(body: any, res: any): Promise<void> {
    try {
      const { domain, ip, app_id } = body
      // 1.Check if there is any information about the application
      const program_result = await this.programEntity.find({
        where: { id: app_id }
      })
      if (program_result.length === 0) {
        res.json({ status: "success", message: "未找到应用信息！" })
        return
      }
      const [{ status: program_status, name: program_name }] = program_result
      if (program_status === 0) {
        res.json({ status: "success", message: "应用未开启授权验证！" })
        return
      }
      // 2.Check if there are authorization records
      const author_result = await this.authorizationEntity.find({
        where: [
          {
            app_id: app_id,
            body: domain,
            type: 0
          },
          {
            app_id: app_id,
            body: ip,
            type: 1
          }
        ]
      })
      if (author_result.length === 0) {
        // If unauthorized, record pirated information
        const data = {
          app_name: program_name,
          app_id: app_id,
          domain: domain,
          ip: ip,
          check_date: getCurrentDate()
        }
        await this.piracyService.record(data)
        res.json({
          status: "error",
          message: "授权验证失败！请联系应用管理员！"
        })
        return
      }
      // 3.Check if the authorization status is normal
      const [{ status: author_status }] = author_result
      if (author_status === 0) {
        res.json({
          status: "error",
          message: "授权已被冻结！请联系应用管理员！"
        })
        return
      }
      // 4.Check if authorization has expired
      const [{ over_date }] = author_result
      const current_date = getCurrentDate()
      if (current_date > over_date) {
        res.json({
          status: "error",
          message: "授权已过期！请联系应用管理员！"
        })
        return
      }
      res.json({ status: "success", message: "授权验证成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Obtain the number of genuine authorization
   * @param res
   */
  public async count(res: any): Promise<void> {
    try {
      const data = await this.authorizationEntity.count()
      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Add authorization based on order
   * @param order
   */
  public async addBasedOrder(order: any): Promise<any> {
    try {
      await this.authorizationEntity.save(order)
    } catch (err) {
      console.log(err)
    }
  }
}
